package com.example.testplatform.aspect;

import com.example.testplatform.annotation.RequirePermission;
import com.example.testplatform.common.JwtTokenUtil;
import com.example.testplatform.common.Result;
import com.example.testplatform.entity.User;
import com.example.testplatform.service.RoleMenuService;
import com.example.testplatform.service.UserService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.List;

/**
 * 权限控制切面
 * 实现基于注解的权限控制逻辑
 */
@Aspect
@Component
public class PermissionAspect {
    
    private static final Logger logger = LoggerFactory.getLogger(PermissionAspect.class);
    
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    
    @Autowired
    private UserService userService;
    
    @Autowired
    private RoleMenuService roleMenuService;
    
    /**
     * 定义切点：拦截带有@RequirePermission注解的方法
     */
    @Pointcut("@annotation(com.example.testplatform.annotation.RequirePermission)")
    public void permissionPointCut() {}
    
    /**
     * 环绕通知，进行权限验证
     */
    @Around("permissionPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        // 获取当前请求
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        
        // 获取Authorization头
        String authorizationHeader = request.getHeader("Authorization");
        
        if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) {
            logger.warn("未提供有效的令牌");
            return Result.unauthorized();
        }
        
        // 提取令牌
        String jwtToken = authorizationHeader.substring(7);
        
        try {
            // 从令牌中获取用户名
            String username = jwtTokenUtil.getUsernameFromToken(jwtToken);
            
            // 查询用户信息
            User user = userService.getByUsername(username);
            if (user == null) {
                logger.warn("用户不存在: {}", username);
                return Result.fail(401, "用户不存在");
            }
            
            // 获取方法上的RequirePermission注解
            MethodSignature signature = (MethodSignature) point.getSignature();
            Method method = signature.getMethod();
            RequirePermission permission = method.getAnnotation(RequirePermission.class);
            
            // 检查是否需要超级管理员权限
            if (permission.requireAdmin()) {
                if (!"admin".equals(user.getRole())) {
                    logger.warn("非超级管理员，无权访问: {}", username);
                    return Result.fail(403, "权限不足，需要超级管理员权限");
                }
            } else {
                // 检查是否需要特定权限
                String[] permissions = permission.value();
                if (permissions != null && permissions.length > 0) {
                    // 获取用户的角色ID
                    Long roleId = user.getId(); // 这里假设用户ID就是角色ID，实际应该是user.getRoleId()
                    
                    // 获取用户拥有的菜单ID列表
                    List<Long> menuIds = roleMenuService.getMenuIdsByRoleId(roleId);
                    
                    // 检查用户是否拥有所需的权限
                    boolean hasPermission = false;
                    for (String perm : permissions) {
                        // 这里需要根据权限编码查询对应的菜单ID
                        // 实际应该有一个方法来根据权限编码获取菜单ID
                        // 为了简化，这里我们假设权限编码就是菜单ID
                        try {
                            Long menuId = Long.parseLong(perm);
                            if (menuIds.contains(menuId)) {
                                hasPermission = true;
                                break;
                            }
                        } catch (NumberFormatException e) {
                            logger.warn("无效的权限编码: {}", perm);
                        }
                    }
                    
                    if (!hasPermission) {
                        logger.warn("权限不足，无法访问: {}", username);
                        return Result.fail(403, "权限不足，无法访问此资源");
                    }
                }
            }
            
            // 有权限，继续执行原方法
            return point.proceed();
            
        } catch (Exception e) {
            logger.error("权限验证失败: {}", e.getMessage());
            return Result.fail(401, "认证失败");
        }
    }
}